/*
 * @Author: ZhangZhao zhangzhao@sinhmicro.com.cn
 * @Date: 2022-09-26 11:48:27
 * @LastEditors: ZhangZhao zhangzhao@sinhmicro.com.cn
 * @LastEditTime: 2022-09-30 11:12:30
 * @Description: breath led drive
 */

#include "sbled.h"
#include "hal/inc/smart-pwm.h"
#include "ec_app_config.h"


uint8_t sbled1_pwm4;

#if (CONFIG_USING_SBLED == 1)
idata sbled_data_t sbled_data[SBLED_NUM];
idata breath_config_t breath_config;

code uint8_t sbled_to_cc_map[SBLED_NUM] = {
    SBLED_0_TO_CC,
#if (SBLED_NUM > 1)
    SBLED_1_TO_CC,
#endif
#if (SBLED_NUM > 2)
    SBLED_2_TO_CC,
#endif
#if (SBLED_NUM > 3)
    SBLED_3_TO_CC,
#endif
#if (SBLED_NUM > 4)
    SBLED_4_TO_CC,
#endif
};

static uint8_t sbled_get_step(uint8_t steps_total);

void preload(void)
{
    T2EN = 0;
    TRL2 = 0xFE;
    TRH2 = 0xFF;
    T2EN = 1;
    TRL2 = TIMER2_RELOAD_VALUE;
    TRH2 = TIMER2_RELOAD_VALUE >> 8;
}

void sbled_init(void)
{
    // breath_config.br_on_tim  = SBLED_BR_ON_TIM;
    // breath_config.br_off_tim = SBLED_BR_OFF_TIM;
#if (CONFIG_SBLED_TIM == 1)
    breath_config.on_tim  = SBLED_ON_TIM;
    breath_config.off_tim = SBLED_OFF_TIM;
#endif

    TCON0 = TCON0_VAL_TIMER2;

    // TRL2 = 0xfe;
    // TRH2 = 0xff; 

    // PWMPOL = PWMPOL | 0x78;

    PWMPOL = PWMPOL | 0x50;

    // PWM3CMPL = 0xff;
    // PWM3CMPH = 0xff;

    PWM4CMPL = 0xff;
    PWM4CMPH = 0xff;

    // PWM5CMPL = 0xff;
    // PWM5CMPH = 0xff;

    PWM6CMPL = 0xff;
    PWM6CMPH = 0xff;

    // PWMEN = PWMEN | 0x78;
    PWMEN = PWMEN | 0x50;

    // T2EN = 1;

    // TRL2 = TIMER2_RELOAD_VALUE;
    // TRH2 = TIMER2_RELOAD_VALUE >> 8; 

    preload();

    MFP1 = SBLED1_PWM4_DIABLE;
    sbled1_pwm4 = SBLED1_PWM4_DIABLE;

    // MFP2 = (MFP2 & 0x7c) | (1 << 7);
    // MFP1 = (MFP1 & 0xc0) | (1 << 0 | 1 << 2 | 1 << 4);
    // MFP1 = (MFP1 & 0xcc) | (1 << 0 | 1 << 4);

    /* P07 R P05 G*/
    // MFP1 = (MFP1 & ~0xCC);
    
    /* P07 R*/
    // P0OE &= ~(1 << 7);

    // /* P04 B */
    // MFP1 = (MFP1 & ~0x03); 
    // P0OE &= ~(1 << 4);
    // P0ODAT |= (1 << 4);

    // /* P06 W */
    // MFP1 = (MFP1 & ~0x30);
    // P0OE &= ~(1 << 6);
    // P0ODAT |= (1 << 6);

    /* P05 G */
    // P0OE &= ~(1 << 5);
}

sbled_sta_t sbled_get_state(sbled_id_t sbled)
{
    return sbled_data[sbled].state;
}

void sbled_set_state(sbled_id_t sbled, sbled_sta_t state)
{
    sbled_data[sbled].state = state;
}

#if (CONFIG_SBLED_BR_NUM == 1)
void sbled_start_breath(sbled_id_t sbled, uint8_t breath_num)
{
    sbled_data[sbled].breath_num = breath_num;
}
#endif

void sbled_off(sbled_id_t sbled)
{
    sbled_data[sbled].state = SBLED_STA_OFF;
#if (CONFIG_SBLED_BR_NUM == 1)
    sbled_data[sbled].breath_num = 0;
#endif
    /*if(sbled == 0){
        P0OE &= ~(1 << 7);
    } else if(sbled == 1){
        P0OE &= ~(1 << 4);
        P0ODAT &= ~(1 << 4);
    }else if(sbled == 2){
        P0OE &= ~(1 << 6);
        P0ODAT &= ~(1 << 6);
    }else{
        P0OE &= ~(1 << 5);
        P0ODAT &= ~(1 << 5);
    } */
}

void sbled_on(sbled_id_t sbled)
{
    sbled_data[sbled].state = SBLED_STA_ON;
#if (CONFIG_SBLED_BR_NUM == 1)
    sbled_data[sbled].breath_num = 0;
#endif
    /*if(sbled == 0){
        P0O_7 = 0;
        P0OE |= (1 << 7);
    } else if(sbled == 1){
        P0OE |= (1 << 4);
        P0ODAT &= ~(1 << 4); 
    }else if(sbled == 2){
        P0OE |= (1 << 6);
        P0ODAT &= ~(1 << 6);
    }else{
        P0OE |= (1 << 5);
        P0ODAT &= ~(1 << 5);
    } */
}

void sbled_breath_on_start(sbled_id_t sbled)
{
    sbled_data[sbled].brightness = SBLED_BRIGHTNESS_MIN;
    sbled_data[sbled].state = SBLED_STA_BR_ON;
#if (CONFIG_SBLED_BR_NUM == 1)
    sbled_data[sbled].breath_num = 0;
#endif
}

void sbled_breath_off_start(sbled_id_t sbled)
{
    sbled_data[sbled].brightness = SBLED_BRIGHTNESS_MAX;
    sbled_data[sbled].state = SBLED_STA_BR_OFF;
#if (CONFIG_SBLED_BR_NUM == 1)
    sbled_data[sbled].breath_num = 0;
#endif
}

void sbled_off_all(void)
{
#if (SBLED_NUM > 2)
    uint8_t i;
    for (i = 0; i < SBLED_NUM; i++)
    {
        sbled_off(i);
    }
#else
    sbled_off(SBLED_0);
    sbled_off(SBLED_1);
#endif
}

void sbled_on_all(void)
{
#if (SBLED_NUM > 2)
    uint8_t i;
    for (i = 0; i < SBLED_NUM; i++)
    {
        sbled_on(i);
    }
#else
    sbled_on(SBLED_0);
    sbled_on(SBLED_1);
#endif
}

#if (CONFIG_SBLED_TIM == 1)
void sbled_set_config(uint8_t br_on_tim, uint8_t br_off_tim, uint8_t on_tim, uint8_t off_tim)
{
    breath_config.br_on_tim  = br_on_tim;
    breath_config.br_off_tim = br_off_tim;
    breath_config.on_tim  = on_tim;
    breath_config.off_tim = off_tim;
}
#else
void sbled_set_config(uint8_t br_on_tim, uint8_t br_off_tim)
{
    breath_config.br_on_tim  = br_on_tim;
    breath_config.br_off_tim = br_off_tim;
}
#endif

#if (CONFIG_SBLED_BR_NUM == 1)
bool sbled_is_breath(sbled_id_t sbled)
{
    return ((sbled_data[sbled].breath_num) || (sbled_data[sbled].state != SBLED_STA_OFF));
}
#endif

static uint8_t sbled_get_step(uint8_t steps_total)
{
    return ((SBLED_BRIGHTNESS_MAX - SBLED_BRIGHTNESS_MIN) / (uint16_t)steps_total);
}

void sbled_handle_10ms(void)
{
#if (SBLED_NUM > 1)
    uint8_t sbled_idx;
    uint8_t mfp1_change;

    mfp1_change = 0;
    if (sbled1_pwm4 != MFP1) {
        MFP1 = SBLED1_PWM4_DIABLE;
        mfp1_change = 1;
    }

    for (sbled_idx = 0; sbled_idx < SBLED_NUM; sbled_idx++) {
        switch (sbled_data[sbled_idx].state) {
            case SBLED_STA_BR_ON:
                sbled_data[sbled_idx].brightness += (SBLED_BRIGHTNESS_MAX / 50)/* sbled_get_step(breath_config.br_on_tim) */;
                if (sbled_data[sbled_idx].brightness > SBLED_BRIGHTNESS_MAX) {
                    sbled_data[sbled_idx].brightness = SBLED_BRIGHTNESS_MAX;
                    sbled_data[sbled_idx].state = SBLED_STA_ON;
#if (CONFIG_SBLED_TIM == 1)
                    sbled_data[sbled_idx].hold_time = 0;
#endif
                }
                break;
            
            case SBLED_STA_BR_OFF:
                if (sbled_data[sbled_idx].brightness > (SBLED_BRIGHTNESS_MAX / 100)/* sbled_get_step(breath_config.br_off_tim) */) {
                    sbled_data[sbled_idx].brightness -= (SBLED_BRIGHTNESS_MAX / 100)/* sbled_get_step(breath_config.br_off_tim) */;
                } else {
                    sbled_data[sbled_idx].brightness = SBLED_BRIGHTNESS_MIN;
                    sbled_data[sbled_idx].state = SBLED_STA_OFF;
#if (CONFIG_SBLED_TIM == 1)
                    sbled_data[sbled_idx].hold_time = 0;
#endif
                }
                break;

            case SBLED_STA_ON:
                sbled_data[sbled_idx].brightness = SBLED_BRIGHTNESS_MAX;
    #if((CONFIG_SBLED_TIM == 1) && (CONFIG_SBLED_BR_NUM == 1))
                if (sbled_data[0].hold_time < breath_config.on_tim) {
                    sbled_data[0].hold_time++;
                } else if (sbled_data[0].breath_num) {
                    sbled_data[0].breath_num--;
                    sbled_data[0].state = SBLED_STA_BR_OFF;
                }
    #else
        #if (CONFIG_SBLED_TIM == 1)
                    if (sbled_data[0].hold_time < breath_config.on_tim) {
                        sbled_data[0].hold_time++;
                    }
        #endif
        #if (CONFIG_SBLED_BR_NUM == 1)
                    if (sbled_data[0].breath_num) {
                        sbled_data[0].breath_num--;
                        sbled_data[0].state = SBLED_STA_BR_OFF;
                    }
        #endif
    #endif
                break;

            case SBLED_STA_OFF:
                sbled_data[sbled_idx].brightness = SBLED_BRIGHTNESS_MIN;
    #if((CONFIG_SBLED_TIM == 1) && (CONFIG_SBLED_BR_NUM == 1))
                if (sbled_data[0].hold_time < breath_config.off_tim) {
                    sbled_data[0].hold_time++;
                } else if (sbled_data[0].breath_num) {
                    sbled_data[0].state = SBLED_STA_BR_ON;
                }
    #else
        #if (CONFIG_SBLED_TIM == 1)
                if (sbled_data[0].hold_time < breath_config.off_tim) {
                    sbled_data[0].hold_time++;
                }
        #endif
        #if (CONFIG_SBLED_BR_NUM == 1)
                if (sbled_data[0].breath_num) {
                    sbled_data[0].state = SBLED_STA_BR_ON;
                }
        #endif
    #endif
                break;
        }
        // spwm_set_duty_relative_max_val(2, sbled_to_cc_map[sbled_idx], sbled_data[sbled_idx].brightness);
        t2_set_duty(sbled_to_cc_map[sbled_idx], sbled_data[sbled_idx].brightness);
    }

    if (mfp1_change) {
        preload();
    }
    MFP1 = sbled1_pwm4;

#else
        switch (sbled_data[0].state) {
            case SBLED_STA_BR_ON:
                sbled_data[0].brightness += sbled_get_step(breath_config.br_on_tim);
                if (sbled_data[0].brightness > SBLED_BRIGHTNESS_MAX) {
                    sbled_data[0].brightness = SBLED_BRIGHTNESS_MAX;
                    sbled_data[0].state = SBLED_STA_ON;
    #if (CONFIG_SBLED_TIM == 1)
                    sbled_data[0].hold_time = 0;
    #endif
                }
                break;
            
            case SBLED_STA_BR_OFF:
                if (sbled_data[0].brightness > sbled_get_step(breath_config.br_off_tim)) {
                    sbled_data[0].brightness -= sbled_get_step(breath_config.br_off_tim);
                } else {
                    sbled_data[0].brightness = SBLED_BRIGHTNESS_MIN;
                    sbled_data[0].state = SBLED_STA_OFF;
    #if (CONFIG_SBLED_TIM == 1)
                    sbled_data[0].hold_time = 0;
    #endif
                }
                break;

            case SBLED_STA_ON:
                sbled_data[0].brightness = SBLED_BRIGHTNESS_MAX;
    #if((CONFIG_SBLED_TIM == 1) && (CONFIG_SBLED_BR_NUM == 1))
                if (sbled_data[0].hold_time < breath_config.on_tim) {
                    sbled_data[0].hold_time++;
                } else if (sbled_data[0].breath_num) {
                    sbled_data[0].breath_num--;
                    sbled_data[0].state = SBLED_STA_BR_OFF;
                }
    #else
        #if (CONFIG_SBLED_TIM == 1)
                    if (sbled_data[0].hold_time < breath_config.on_tim) {
                        sbled_data[0].hold_time++;
                    }
        #endif
        #if (CONFIG_SBLED_BR_NUM == 1)
                    if (sbled_data[0].breath_num) {
                        sbled_data[0].breath_num--;
                        sbled_data[0].state = SBLED_STA_BR_OFF;
                    }
        #endif
    #endif
                break;

            case SBLED_STA_OFF:
                sbled_data[0].brightness = SBLED_BRIGHTNESS_MIN;
    #if((CONFIG_SBLED_TIM == 1) && (CONFIG_SBLED_BR_NUM == 1))
                if (sbled_data[0].hold_time < breath_config.off_tim) {
                    sbled_data[0].hold_time++;
                } else if (sbled_data[0].breath_num) {
                    sbled_data[0].state = SBLED_STA_BR_ON;
                }
    #else
        #if (CONFIG_SBLED_TIM == 1)
                if (sbled_data[0].hold_time < breath_config.off_tim) {
                    sbled_data[0].hold_time++;
                }
        #endif
        #if (CONFIG_SBLED_BR_NUM == 1)
                if (sbled_data[0].breath_num) {
                    sbled_data[0].state = SBLED_STA_BR_ON;
                }
        #endif
    #endif
            break;
    }
    spwm_set_duty_relative_max_val(2, sbled_to_cc_map[0], sbled_data[0].brightness);
#endif
}
#endif
